#include "serport.h"
#include "rs232_interface.h"

wxSerialPort *serial_port=NULL;
NewPacketEventFunction g_pef=NULL;
bool Parser_ThreadProc_IsRuning=false;
bool Parser_ThreadProc_killrequest=false;
   

char ToHex(char b)
{
	char  c = b & 0x0f;
    if (c>9) c += 'A'-10;
    else c += '0';

	return c;
}

char Hex2Bin(char hex)
{
	char bin;
		bin = (hex <= '9' ? hex - '0' : hex - '0' - 7) ;
	return bin;
}

void TranslateToBinaryData(unsigned char *hexdata, unsigned char hexdata_len,unsigned char  *binarydata,unsigned char *binarydata_len)
{
	*binarydata_len=0;

	for(unsigned char i=0;i<hexdata_len;i+=2)
	{
	 	binarydata[(*binarydata_len)++]=(Hex2Bin(hexdata[i])<<4)|(Hex2Bin(hexdata[i+1]));
	}
}



#define RECEIVE_MAX_PACKET_SIZE 100
#define RECEIVE_DATA_PACKET_SIZE 50



DWORD WINAPI Parser_ThreadProc(void)  
{  	
	unsigned char u_c,state=0;
	unsigned char packet_h_pos=0;
	unsigned char receive_data_packet[RECEIVE_DATA_PACKET_SIZE];
	unsigned char receive_packet[RECEIVE_MAX_PACKET_SIZE];
	unsigned char receive_data_packet_len;

    Parser_ThreadProc_IsRuning=true;
	do 
	{
		if(serial_port->Read((char *)&u_c,1)==1)
		{
			if((state==0) && (u_c=='[')) state=1; // begin packet
		
			if(state==1)
			{
				receive_packet[packet_h_pos++]=u_c;

				if(u_c==']')
				{
					if(receive_packet[1]!='e')
					{
						TranslateToBinaryData(receive_packet+2,packet_h_pos-3,receive_data_packet,&receive_data_packet_len);
						if(g_pef!=NULL) g_pef((char)receive_packet[1],receive_data_packet,receive_data_packet_len);
					} else
					{
						receive_packet[packet_h_pos-1]=0;
						g_pef((char)receive_packet[1],receive_packet+2,packet_h_pos-3);
					}
					packet_h_pos=0;
					state=0;
				}

				if((packet_h_pos+2)>RECEIVE_MAX_PACKET_SIZE)
				{
					packet_h_pos=0;
					state=0;
				}	
			}
		}
	} while (Parser_ThreadProc_killrequest==false);

	Parser_ThreadProc_IsRuning=false;
	return 0;
} 





bool RS232InterfaceInit(LPCWSTR serial_port_name, NewPacketEventFunction pef)
{
	if(pef==NULL) return 0;

	serial_port = new wxSerialPort();
	if(serial_port->OpenDevice(serial_port_name,115200)!=0) return false;
	g_pef=pef;
	
	Parser_ThreadProc_killrequest=false;
	CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Parser_ThreadProc, NULL, 00, NULL); 

	return true;
}



#define MAX_PACKET_SIZE 50
unsigned char send_packet_buffer[MAX_PACKET_SIZE*2];

bool RS232WritePacket(char packet_type,unsigned char *data, int data_len)
{
	if(serial_port==NULL) return false;
	if(data_len>=MAX_PACKET_SIZE) return false;

	memset(send_packet_buffer,0,MAX_PACKET_SIZE*2); /* clead buffer - good idea for beter debuging*/

	send_packet_buffer[0]=(unsigned char)'[';
	send_packet_buffer[1]=packet_type;

		for(int i=0;i<data_len;i++)
		{
			send_packet_buffer[(i*2)+2]=ToHex(data[i]>>4);
			send_packet_buffer[(i*2)+1+2]=ToHex(data[i]);
		}
		
	send_packet_buffer[(data_len*2)+2]=(unsigned char)']';
	serial_port->Write((char *)send_packet_buffer,(data_len*2)+3);

	return true;
}


bool RS232InterfaceDeInit(void)
{
	serial_port->CloseDevice();

	while(Parser_ThreadProc_IsRuning)
	{
		Parser_ThreadProc_killrequest=true;
		Sleep(100);
	}

	delete serial_port;
	return true;
}
